import 'dart:async';

import 'package:flutter/material.dart';
import 'package:kq_flutter_core_widget/widgets/image/kq_image.dart';


class KqSwiper2<T extends IShowData> extends StatefulWidget {
  /// 展示的数据
  final List<T> showData;

  /// 点击回调
  final Function(int index, T data)? onTap;

  /// 界面宽度
  final double width;

  /// 界面高度
  final double height;

  /// 是否开启自动滑动
  final bool isAutoSlide;

  ///指示器
  final IIndicator? indicator;

  const KqSwiper2(
      {super.key,
      required this.showData,
      this.onTap,
      this.width = 360,
      this.height = 250,
      this.isAutoSlide = true,
      this.indicator});

  @override
  State<StatefulWidget> createState() => _KqSwiperState<T>();
}

class _KqSwiperState<T extends IShowData> extends State<KqSwiper2<T>> {
  static const int maxInt = 100000000;

  /// 执行自动滑动的时间间隔s
  static const int slideTime = 6;

  /// 当前正在显示的图片
  int index = 0;

  ///定时滑动计时器
  Timer? _timer;

  /// 指示器
  IIndicator? _indicator;

  /// 当Indicator的类型为widget时的widget列表值
  List<Widget>? _indicatorWidgetList;

  PageController controller = PageController();

  @override
  void initState() {
    _indicator = widget.indicator ?? DrawIndicator();
    _startSlide();
    _initWidgetIndicator(index);

    controller.addListener(() {
      if (controller.page != null) {
        if (controller.page! % 1 == 0) {
          _startSlide();
        } else {
          _timer?.cancel();
        }
      }
    });
    super.initState();
  }

  void _initWidgetIndicator(int index) {
    if (_indicator?.type == IndicatorType.widget) {
      _indicatorWidgetList =
          _indicator?.onIWidget(widget.showData.length, index);
    }
  }

  void _startSlide() {
    if (widget.isAutoSlide) {
      if (_timer == null || !_timer!.isActive) {
        //计时器，每1毫秒执行一次
        const period = Duration(seconds: slideTime);
        _timer = Timer.periodic(period, (timer) {
          if (index == widget.showData.length - 1) {
            index = 0;
          } else {
            index++;
          }
          controller.nextPage(
              duration: const Duration(milliseconds: 200), curve: Curves.ease);
        });
      }
    }
  }

  @override
  void dispose() {
    //退出时关闭计时器防止内存泄露
    _timer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: widget.height,
      width: widget.width,
      child: RepaintBoundary(
          child: Stack(
              alignment: Alignment.center,
              fit: StackFit.expand,
              children: [
            PageView.builder(
              itemCount: maxInt,
              allowImplicitScrolling: true,
              controller: controller,
              onPageChanged: (index) {
                this.index = index % widget.showData.length;
                _initWidgetIndicator(this.index);
                setState(() {});
              },
              itemBuilder: (context, index) {
                return InkWell(
                  onTap: () {
                    widget.onTap?.call(this.index, widget.showData[this.index]);
                  },
                  child: _renderImage(),
                );
              },
            ),
            IgnorePointer(
              child: CustomPaint(
                painter: _SwiperIndicatorPinter(
                    this, widget.showData.length, index, _indicator!),
              ),
            ),
            Positioned(
                bottom: 10,
                child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: _indicatorWidgetList ?? [])),
          ])),
    );
  }

  _renderImage() {
    var imageType = widget.showData[index % widget.showData.length].type;
    return KqImage.custom(
      imageType: imageType,
      width: 200,
      height: 200,
      url: widget.showData[index % widget.showData.length].path,
      fit: BoxFit.cover,
      errorImageBuilder: (context, url, error) =>
      const ColoredBox(
        color: Colors.white,
        child: SizedBox(width: 200, height: 200),
      ),
      placeholderBuilder: (context, url) => const ColoredBox(
        color: Colors.white,
        child: SizedBox(width: 200, height: 200),
      ),
    );
  }
}

class _SwiperIndicatorPinter extends CustomPainter {
  final _KqSwiperState state;
  final int _length;
  final int _index;
  final IIndicator _indicator;

  Paint selfPaint = Paint()
    ..color = Colors.blue
    ..style = PaintingStyle.fill
    ..isAntiAlias = true
    ..strokeCap = StrokeCap.butt
    ..strokeWidth = 30.0;

  _SwiperIndicatorPinter(
      this.state, this._length, this._index, this._indicator);

  @override
  void paint(Canvas canvas, Size size) {
    if (_indicator.type == IndicatorType.draw) {
      _indicator.onIDraw(
          canvas, _length, _index, state.widget.width, state.widget.height);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}

/// 文件格式
abstract class IShowData {
  /// 展示的图片路径
  final String path;

  /// 图片路径位置
  final ImageType type;

  IShowData(this.path, this.type);
}

enum IndicatorType {
  /// widget类型
  widget,

  /// 绘制类型
  draw
}

/// 指示器，实现该类进行自定义绘制
abstract class IIndicator {
  final IndicatorType type;

  IIndicator(this.type);

  /// 自定义绘制
  /// length 指示器个数
  /// curIndex 指示器当前位置
  /// w 控件宽度
  /// h 控件高度
  onIDraw(Canvas canvas, int length, int curIndex, double w, double h);

  /// 自定义传widget
  /// length 指示器个数
  /// curIndex 指示器当前位置
  /// return List<Widget> 指示器列表
  List<Widget> onIWidget(int length, int curIndex);
}

/// 传widget的指示器抽象类，传widget的方式需要继承该类实现
abstract class IWidgetIndicator extends IIndicator {
  IWidgetIndicator() : super(IndicatorType.widget);

  @override
  onIDraw(Canvas canvas, int length, int curIndex, double w, double h) {
    ///啥也不干
  }

  @override
  List<Widget> onIWidget(int length, int curIndex) {
    return onWidget(length, curIndex);
  }

  /// 过渡方法
  List<Widget> onWidget(int length, int curIndex);
}

/// 自定义绘制的指示器抽象类，自定义绘制的方式需要继承该类实现
abstract class IDrawIndicator extends IIndicator {
  IDrawIndicator() : super(IndicatorType.draw);

  @override
  onIDraw(Canvas canvas, int length, int curIndex, double w, double h) {
    onDraw(canvas, length, curIndex, w, h);
  }

  @override
  List<Widget> onIWidget(int length, int curIndex) {
    ///啥也不干
    return [];
  }

  /// 过渡方法
  onDraw(Canvas canvas, int length, int curIndex, double w, double h);
}

/// 内置绘制指示器
class DrawIndicator extends IDrawIndicator {
  /// 指示器单个点x方向偏移
  final double _dotOffsetDx = 10;

  /// 指示器单个点y方向偏移
  final double _dotOffsetDy = 10;

  /// 指示器点的半径
  final double _dotRadius = 4;

  /// 指示器画笔
  final Paint _paint = Paint()
    ..style = PaintingStyle.fill
    ..isAntiAlias = true
    ..strokeCap = StrokeCap.butt
    ..strokeWidth = 30.0;

  @override
  onDraw(Canvas canvas, int length, int curIndex, double w, double h) {
    for (int i = 0; i < length; i++) {
      //绘制当前指示器
      if (i == curIndex) {
        _paint.color = Colors.blue;
        canvas.drawCircle(
            Offset(
                (w / 2 - (_dotRadius * 2 + (length - 1) * _dotOffsetDx) / 2) +
                    (_dotRadius * 2 + _dotOffsetDx) * i,
                h - _dotOffsetDy),
            _dotRadius,
            _paint);
        // 绘制非当前的其它指示器
      } else {
        _paint.color = Colors.grey;
        canvas.drawCircle(
            Offset(
                (w / 2 - (_dotRadius * 2 + (length - 1) * _dotOffsetDx) / 2) +
                    (_dotRadius * 2 + _dotOffsetDx) * i,
                h - _dotOffsetDy),
            _dotRadius,
            _paint);
      }
    }
  }
}

/// 内置widget指示器
class WidgetIndicator extends IWidgetIndicator {
  @override
  List<Widget> onWidget(int length, int curIndex) {
    List<Widget> widgets = [];
    for (int i = 0; i < length; i++) {
      if (curIndex == i) {
        widgets.add(Text(
          (i + 1).toString(),
          style:
              const TextStyle(color: Colors.red, backgroundColor: Colors.white),
        ));
      } else {
        widgets.add(Text(
          (i + 1).toString(),
          style: const TextStyle(
              color: Colors.black, backgroundColor: Colors.white),
        ));
      }
    }
    return widgets;
  }
}
